<html xmlns="http://www.w3.org/1999/xhtml" id="class-inheritance"
      xmlns:d="docbook">
<head>
    <title>拡張クラス</title>
</head>

<body>

<h1>拡張クラス</h1>
 
<p>この章では、<glossterm baseform="view">ビュー</glossterm>、<glossterm baseform="method">メソッド</glossterm>、<glossterm baseform="attribute">属性</glossterm>といった基本的なLZXコンセプトに親しむことができます。<glossterm>オブジェクト指向プログラミング</glossterm>（OOP）のコンセプトに慣れていれば役には立ちますが、必ずしも必要というわけではありません。LZXにおけるクラスについての入門書は、<xref
linkend="introductory-classes"/>を参照してください。
</p>
<h2>概要</h2>

<p>継承によって、すでに定義されているクラスからカスタムクラスを生成することができます。この利点は、大部分が似ているけれどほんのちょっとの違いがあるようなクラスを生成したい時、その度ごとにたくさんのロジックを書かなくてもよくなるということです。</p>

<p><dfn>subclass</dfn>とは、他のクラスから派生したクラスのことです。派生元のクラスは、<dfn>superclass</dfn>（上位クラス）と言われます。サブクラスは、その上位クラスからメソッドと属性とを<dfn>継承する</dfn>と言われます。<tagname>view</tagname>のような、上位クラスの視覚要素もまた、各サブクラスに継承されます。LZXにおいては、サブクラスを生成するために、<tagname
link="true">class</tagname>タグに（対して）<attribute>extends</attribute>属性を使用します。</p>

<pre>
&lt;class name="myclass" extends="mysuperclass"&gt;
   ...
&lt;/class&gt;
</pre>

<p>
<attribute>extends</attribute>属性を使わずに生成したクラスはどんなものでも、<tagname>view</tagname>のサブクラスとみなされます。<tagname>view</tagname>からの全てのメソッドとプロパティはサブクラスによって継承されます。これらの2つの宣言は同じことをしています。
</p>

<pre>
&lt;class name="myclass"/&gt;
&lt;class name="myclass" extends="view"/&gt;
</pre>
<fixme> explicitly explain multiple inheritance -- or rather, define single inheritance --superclass and subclass, etc
</fixme>
<p>継承は任意の深さにまで続けていくことができますが、拡張できるのはクラスの宣言につき1つのクラスだけです。複数継承はサポートされていません。つまり、1つ以上の現存クラスを拡張した新しいクラスを生成することはできません。クラス内のメソッド、変数、ビューは各レベルを通じて継承されます。</p>

<example title="Inheritance chain">
&lt;canvas debug="true" height="125"&gt;
  &lt;debug x="80" y="5" width="170" height="112"/&gt;

  &lt;class name="top"&gt;
    &lt;attribute name="myfoo" value="bar" type="string"/&gt;
  &lt;/class&gt;
  
  &lt;class name="middle" extends="top"&gt;
    &lt;method name="doit"&gt;
      Debug.write("myfoo is " + this.myfoo);
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;class name="bottom" extends="middle"&gt;
    &lt;button text="clickme" onclick="parent.doit()"/&gt;
  &lt;/class&gt;
  
  &lt;bottom/&gt;
&lt;/canvas&gt;
</example>

<p>クラス定義は属性のデフォルト値を含みます。例えば、ビューを<i>拡張する</i>クラスはデフォルトの<attribute>width</attribute>と<attribute>height</attribute>属性を持つことができます。</p>

<example executable="false">
&lt;class name="myClass" width="50" height="50"/&gt; <co>
<p><code>myClass</code>というクラスとタグを定義する</p></co>
&lt;myClass/&gt; <co><p>widthとheightの値を50にして、<code>myClass</code>のインスタンスを生成する</p></co>
&lt;myClass width="100"/&gt; <co><p>widthの値を100、heightの値を50にして、<code>myClass</code> のインスタンスを生成する</p></co></example>



<!--=================================== --> 
<!-- Overriding methods and attributes  -->
<!--=================================== --> 
<h2>メソッドと属性の無効化</h2>
<p>サブクラスは、上位クラスを<dfn>無効化する</dfn>、つまり、異なる実行を提供する、ことができます。例えば、上位クラスのメソッドが<code>method(arg1, arg2)</code>のような2つの引数を持つとしたら、サブクラスでは<code>method(arg1, arg2, arg3)</code>のように3つ目の引数を持つことが選べます。
</p>
<p>
LZXはメソッドの<glossterm>オーバーロード</glossterm>をサポートしていません。つまり、1つのクラス内で同一の名前のメソッドを持つことはできないということです。ランタイムは呼び出しているメソッドの名前のみを“気にかけ”るのです。もし、クラス定義で2つ以上の同名のメソッドを定義した場合には、コンパイル警告を受けることになるでしょう。
</p>
<fixme>
explain behavior -- what happens if you overload
</fixme>

<p><tagname link="true">attribute</tagname>タグ使って新しい値を定義するか、あるいは<tagname>class</tagname>宣言そのものの中でそれを属性として定義することによって、継承された属性を修正することができます。
</p>

<example title="Inheriting Properties">
&lt;canvas height="100"&gt;
  &lt;!-- create a simplelayout so embedded views are laid out  --&gt;
  &lt;!-- on top of each other.                                 --&gt;
  &lt;class name="class1" layout="class: simplelayout; spacing: 2"&gt;
    &lt;attribute name="label" value="class1 label" type="string"/&gt;
    &lt;text&gt;from class1&lt;/text&gt;
    &lt;button text="${classroot.label}"/&gt;
  &lt;/class&gt;

  &lt;!-- overrides class1's label; inherits text and button --&gt;
  &lt;class name="class2" extends="class1" label="class2 label"&gt;
    &lt;text&gt;from class2&lt;/text&gt;
  &lt;/class&gt;

  &lt;!-- inherit class1's text and button; inherit class2's text --&gt;
  &lt;class name="class3" extends="class2"&gt;
    &lt;text&gt;from class3&lt;/text&gt;
  &lt;/class&gt;
  &lt;class3/&gt;
&lt;/canvas&gt;
</example>

<p>
上位クラスのメソッドを呼び出すために、<code>super</code>キーワードを使うことができます。<code>super</code>キーワードは、同じロジックを再度記述せずに上位クラスのメソッドを拡張したいインスタンス内で便利です。メソッドは、無効にするメソッドを呼ぶ時にだけ、<code>super</code>を使うことができます。つまり、サブクラスの<method>myfunc</method>は、<code>super.myfunc()</code>、 <code>super.myotherfunc()</code>だけを呼ぶことができるのです。
</p>

<example title="The super keyword">
&lt;canvas debug="true" height="140"&gt;
  &lt;debug x="60"/&gt;

  &lt;class name="foo"&gt;
    &lt;method name="talk"&gt;
      Debug.write("hello");
    &lt;/method&gt;
    &lt;button text="click" onclick="parent.talk()"/&gt;
  &lt;/class&gt;

  &lt;class name="bar" extends="foo"&gt;
    &lt;method name="talk"&gt;
      super.talk();
      Debug.write("goodbye");
    &lt;/method&gt;
  &lt;/class&gt;

  &lt;bar/&gt;
&lt;/canvas&gt;
</example>
<h3>匿名のメソッドは無効化され得ない</h3>
<p>
イベントハンドラを無効化するためには、そのイベントに名前を付けなければなりません。<tagname link="true">method</tagname> タグの内部で<code>name="" event=" "</code>属性を使用して、イベントに名前を付けることができます。例えば、インスタンス内で無効化できる<code>onclick</code>イベントのためのハンドラを記述したいとします。クラス定義において、このシンタックスを使うでしょう：
</p>
<pre>
    &lt;method name="handleClick" event="onclick"&gt;
</pre>
<p>
<xref linkend="methods-events-attributes"/>で説明されたように、名前を付けずにイベントハンドラを生成することも可能です。しかし、そうすると、イベントはデリゲートのように列をなします。イベントが起こるとき、そのイベントに関連する全てのイベントハンドラが実行されます---いずれも無効化されません。
</p>
<p>
キーは、イベントに関連したメソッドに名前を<i>付けない</i>と、イベントは（ランタイムによって与えられる）特異な名前を持ち、サブクラスやインスタンスにおいてそれを無効化できなくなります（なぜなら、付けられた名前をしらないので）。
</p>
<p>
以下に示す例では、<code>event=""</code>シンタックスを使って定義されている名前を付けられていないイベントハンドラが、オーバーライドされるときに、期待されるような動作をしないことが見て取れます。
</p>
<example title="named events">
&lt;canvas debug="true" height="400"&gt;
  &lt;debug y="200"/&gt;
  &lt;class name="named_way" bgcolor="red" width="40" height="40"&gt;
    &lt;method name="handleClick" event="onclick"&gt;
        Debug.write('original click');
     &lt;/method&gt;
   &lt;/class&gt;

  &lt;class name="annonymous_way" bgcolor="blue" width="40" height="40"&gt;
    &lt;method event="onclick"&gt;
        Debug.write('original click');
     &lt;/method&gt;
   &lt;/class&gt;

   &lt;simplelayout/&gt;
   &lt;named_way&gt;
     &lt;method name="handleClick"&gt;
         Debug.write('overridden method');
     &lt;/method&gt;
   &lt;/named_way&gt;
   &lt;annonymous_way&gt;
     &lt;method event="onclick"&gt;
         Debug.write('annonymous event handler');
     &lt;/method&gt;
   &lt;/annonymous_way&gt;
&lt;/canvas&gt;
</example>

<p>
上位メソッドを使って、新しいメソッド内でオリジナルのクリックノードを呼び出せることを覚えておいてください。
</p>

<example extract="false">
     &lt;method name="handleClick"&gt;
         super.handleClick();
         Debug.write('new click');
     &lt;/method&gt;
</example>

<!--=========== --> 
<!-- Classroot  -->
<!--=========== --> 
<h2>クラスルート</h2>

<p>
<code>classroot</code>プロパティはクラスインスタンスのルート節を示す便利な省略表現です。これは、深くネストしたビューや、クラスのルートの近くにある何かにアクセスする必要があるメソッドによく利用されます。<code>parent</code>や<code>parent.parent</code>、<code>parent.parent.parent</code>などにも同様に使うことができます（リファレンスを含むビューがどの程度深くネスとされているかによります）。が、クラスルートを使うほうが、通常、より合理的です。ステートサブクラスのメンバはクラスルートを定義しません。
</p>

<todo>上の最後の文は、何を意味しているのでしょう？</todo>

<example title="Classroot example">
&lt;canvas debug="true" height="160"&gt;
  &lt;debug x="155" y="10"/&gt;
    
  &lt;!-- class deep --&gt;
  &lt;class name="deep"&gt;
    &lt;attribute name="mytext" value="hello, world" type="string"/&gt;
    
    &lt;view bgcolor="red" width="150" height="150"&gt;
      &lt;view bgcolor="green" width="75%" height="75%"&gt;
        &lt;button text="clickme" width="75%" height="75%"&gt;
          &lt;!-- classroot is a convenient way to access mytext --&gt;
          &lt;method event="onclick"&gt;
            Debug.write("classroot.mytext: " + classroot.mytext);
            Debug.write("parent.parent.parent.mytext: " + 
                        parent.parent.parent.mytext);
          &lt;/method&gt;
        &lt;/button&gt;
      &lt;/view&gt;
    &lt;/view&gt;
  &lt;/class&gt;
  
  &lt;!-- instance of class deep --&gt;
  &lt;deep/&gt;
&lt;/canvas&gt;
</example>

<p>
クラスのルートから<code>classroot</code>を使う際には、注意してください。もし、周囲のクラスがなければ、<code>classroot</code>は定義されません。クラスのルートに所属しているコード内では、<code>this</code>キーワードを使ってください。その一方で、もしクラスのインスタンスが別のクラスの内部に現れたら、そのインスタンスのための<code>classroot</code>は周囲のクラスのルートでしょう。
外のクラスのルートを示すためのショートカットとして、この機能を使ってください。
</p>

<example title="Referring to outer class's root using classroot">
&lt;canvas debug="true" height="200"&gt;
  &lt;debug height="175"/&gt;
  
  &lt;class name="foo"&gt;
    &lt;method name="doit"&gt;
      Debug.write("foo: this is [" + this + "]");
      Debug.write("foo: classroot is [" + classroot + "]");
      Debug.write("foo: classroot.classroot is [" + classroot.classroot + "]");
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;!-- boo contains a foo --&gt;
  &lt;class name="boo"&gt;
    &lt;foo name="myfoo"/&gt;
  &lt;/class&gt;
  
  &lt;!-- goo contains a boo --&gt;
  &lt;class name="goo"&gt;
    &lt;boo name="myboo"/&gt;
    &lt;method event="oninit"&gt;
      myboo.myfoo.doit();
      Debug.write("-----");
      Debug.write("goo: this is [" + this + "]");
      // warning will be displayed -- there is no classroot
      Debug.write("goo: classroot is [" + classroot + "]");
    &lt;/method&gt;
  &lt;/class&gt;
  
  &lt;!-- Make an instance of goo --&gt;
  &lt;goo name="mygoo"/&gt;
&lt;/canvas&gt;
</example>

<!--======= -->
<!-- Text   -->
<!--======= -->
<h2>宣言されたテキスト</h2>

<p>
<tagname link="true">text</tagname>と<tagname
link="true">inputtext</tagname>タグは、本文の内容を保持できるという点において、ビルトインクラスの中でユニークです。
</p>

<example extract="false">
&lt;canvas height="50" layout="y"&gt;
  &lt;inputtext&gt;plain text&lt;/inputtext&gt;
  &lt;text&gt;&lt;i&gt;styled&lt;/i&gt; text&lt;/text&gt;
&lt;/canvas&gt;
</example>

<p>テキストは、特定のXHTMLのマークアップタグと同じように、文字列テキストを含みます。入力テキストは文字列テキストを含みます。</p>

<p>テキストクラスと入力テキストクラスを拡張したクラスはそれぞれ、XHTMLとプレーンテキストを含みます。テキスト内容は、このようなクラスのテキスト属性として有効です。</p>

<example title="Extending text classes">
&lt;canvas height="50" layout="axis: y"&gt;
  &lt;class name="mytext" extends="text"/&gt;
  &lt;class name="myinputtext" extends="inputtext"/&gt;
  &lt;myinputtext&gt;plain text&lt;/myinputtext&gt;
  &lt;mytext&gt;&lt;i&gt;styled&lt;/i&gt; text&lt;/mytext&gt;
&lt;/canvas&gt;
</example>

<p>
<attribute>text</attribute>と名前を付けられた属性を、<code>&lt;attribute name="text"
type="text"&gt;</code>のように<code>text</code>（プレーンテキストに対して）、あるいは<code>html</code>（XHTMLテキストに対して）の値で定義することにより、ユーザ定義クラスもまたテキスト内容を扱うことができます。
また、<code>string</code>という別のテキスト型も有効です。これは、文字列を属性としてセットできますが、テキスト内容は許可しません
</p>

<p>これらの、<code>type="string"</code>を使って定義されている最初のクラスと、<code>type="text"</code>で定義されている2番目のクラスとを比較してみてください。
</p>

<example extract="false">
&lt;class name="stringText"&gt;
  &lt;attribute name="text" type="string"/&gt;
&lt;/class&gt;

&lt;class name="textText"&gt;
  &lt;attribute name="text" type="text"/&gt;
&lt;/class&gt;
</example>

<p>双方とも、テキスト属性で使われることができます。</p>

<pre class="code">
&lt;stringText text="some text"/&gt;
&lt;textText text="some text"/&gt;
</pre>

<p>
<varname>textText</varname>だけが、テキスト内容に使われることができます。以下のstringTextの使用例は無効であり、コンパイル警告を発生させます。
</p>

<pre class="code">
&lt;stringText&gt;some text&lt;/stringText&gt; &lt;!-- This is invalid --&gt;
&lt;textText&gt;some text&lt;/textText&gt;     &lt;!-- This is valid --&gt;
</pre>

<p>
<code>html</code>型の使用は、そのクラスがhtmlテキスト内容を受け入れ可能である、あるいは<attribute>text</attribute>属性を通じてセットするということを宣言します。テキストは、以下のプログラムのように<tagname>b</tagname>や<tagname>a</tagname>といったXHTMLタグを含んでいるかもしれません。
</p>

<example title="Text type: html">
&lt;canvas height="50"&gt;
  &lt;class name="htmlText"&gt;
    &lt;attribute name="text" type="html"/&gt;
    &lt;text resize="true" text="${parent.text}"/&gt;
  &lt;/class&gt;
  
  &lt;simplelayout/&gt;
  &lt;htmlText&gt;
    &lt;b&gt;bold&lt;/b&gt; text declared here with 
    &lt;a href="http://www.laszlosystems.com"&gt;&lt;i&gt;anchor&lt;/i&gt;&lt;/a&gt;
  &lt;/htmlText&gt;
  &lt;htmlText text="&amp;lt;b&amp;gt;bold&amp;lt;/b&amp;gt; text set here"/&gt;
&lt;/canvas&gt;
</example>

<p><code>type="html"</code>ではなく、<code>type="text"</code>によって宣言されているクラス内のXHTMLマークアップは無効であることに注意してください。
</p>

<example extract="false">
&lt;textText&gt;some text&lt;/textText&gt; &lt;!-- valid --&gt;
&lt;textText&gt;some &lt;i&gt;fancy&lt;/i&gt; text&lt;/textText&gt; &lt;!-- invalid --&gt;
&lt;htmlText&gt;some text&lt;/htmlText&gt; &lt;!-- valid --&gt;
&lt;htmlText&gt;some &lt;i&gt;fancy&lt;/i&gt; text&lt;/htmlText&gt; &lt;!-- valid --&gt;
</example>

<p><code>text</code>、あるいは<code>html</code>型のテキスト属性がない状態で宣言されているクラスのテキスト内容は、どんなものでも無効です。
</p>

<example extract="false">
&lt;class name="noText"/&gt;
&lt;noText&gt;some text&lt;/noText&gt; &lt;!-- invalid --&gt;
&lt;noText&gt;some &lt;i&gt;fancy&lt;/i&gt; text&lt;/noText&gt; &lt;!-- invalid --&gt;
</example>

<p>属性名は<code>text</code>でなければなりません。<code>text</code>や<code>html</code>を他のどんな属性の型として使っても、それはエラーとなります。</p>

<example extract="false">
&lt;class name="invalidClass"&gt;
 &lt;attribute name="label" type="text"/&gt; &lt;!-- invalid --&gt;
&lt;/class&gt;
</example>

<!--======= --> 
<!-- Fonts  -->
<!--======= --> 
<h2>フォント継承</h2>

<p>
クラス内に入っているクラスやビューは、それらのフォントや（<attribute>fontstyle</attribute>や<attribute>fontsize</attribute>といった）フォントプロパティを上位クラスから継承します。また、どんなクラスインスタンスも、そのフォントを自身が内包するビューから継承します。フォントは、ビュー階層のどんなポイントであっても無効にでき、どんなサブビューもそれ以降そのフォントを継承します。
</p>

<example title="Inheriting fonts">
&lt;canvas height="50"&gt;
  &lt;font src="helmetr.ttf" name="Helvetica"/&gt;
  &lt;font src="helmetb.ttf" name="Helvetica" style="bold"/&gt;
  
  &lt;class name="foo"&gt;
    &lt;!-- view overrides inherited fontstyle to plain --&gt;
    &lt;view fontstyle="plain" bgcolor="yellow"&gt;
      &lt;!-- text overrides inherited fontsize to 12 --&gt;
      &lt;text fontsize="12"&gt;hello&lt;/text&gt;
    &lt;/view&gt;
  &lt;/class&gt;
  
  &lt;class name="bar" extends="foo" layout="axis: y"&gt;
    &lt;text&gt;goodbye&lt;/text&gt;
  &lt;/class&gt;
  
  &lt;bar font="Helvetica" fontstyle="bold" fontsize="12"/&gt;
&lt;/canvas&gt;
</example>

<!--================ --> 
<!-- Instantiating   -->
<!--================ --> 
<h2>スクリプトを通じてクラスを具体化する（スクリプトによるクラスの具体化）</h2>

<p>
一般的に、オブジェクトの<glossterm>具象化</glossterm>はタグを用いて行われます。例えば、<code>&lt;class name="myclass"&gt;</code>が宣言されているとして、<code>&lt;myclass/&gt;</code>を記述することによってそのクラスのインスタンスを生成することができます。しかしながら、場合によっては、オブジェクトを具象化するのにスクリプトを使う必要があることがあります。スクリプトによるクラスの具象化の構文は以下のようになっています。
</p>

<pre>
var myobject = new myclass(<i>parent</i>, <i>attributes</i>, <i>children</i>, <i>instcall</i>)
</pre>

<p>ここでは、</p>

<ul>
    <li>
	<varname>parent</varname>は節（ノード）階層でのオブジェクトの位置を示します。もし問題がなければ、<code>null</code>を渡すことができます。もし、<code>view</code>のサブクラスを生成しており、parentが<code>null</code>であるならば、<code>canvas</code>がこのオブジェクトのparentとなります。
	</li>
    
    <li>
	<varname>attributes</varname> はオブジェクトに渡される属性値のハッシュです。例えば、新しい <code>view</code>を異なる背景色と幅、高さでインスタンス化したい場合、<code>{bgcolor: 0xff0000, width:
    50, height: 50}</code>を渡すことができます。
    </li>
    
    <li>
	<varname>children</varname>は、このオブジェクトがカプセル化しているchild viewの配列です。LFC instantiatorは、LZX階層に基づいてこの<code>object</code>のchildrenを渡す役割を果たします。一般的に、これにはnullをセットします。
	</li>

    <li>
	<varname>instcall</varname> は、このオブジェクトがいつインスタンス化されるのかを決定するブーリアン値です。もし、falseならば、このオブジェクトのインスタンス化は即座に行われますが、そうでなければ、インスタンス化は残りのviewシステムと同期を取って行われます。インスタンス化について理解するには、<xref
    linkend="initialization-and-instantiation"/>を参照のこと。
	</li>
</ul>

<p>これら全てのパラメーターはオプションです。これらの引数を全くセットしない（例：<code>new myclass()</code>）のは、<code>new myclass(null,
null, null, 0)</code>と同じことになります。
</p>

<p>以下の例では、スクリプトによって新しいオブジェクトをインスタンス化し、それを別のviewに加える方法を紹介しています。</p>

<example title="Script instantiation">
&lt;canvas height="120"&gt;
  &lt;class name="mybox"&gt;
    &lt;view bgcolor="${parent.bgcolor}" width="50" height="50"/&gt;
  &lt;/class&gt;
  
  &lt;view name="redbox" bgcolor="red" width="100" height="100"/&gt;
  
  &lt;!-- Create new mybox with cyan bgcolor and place it in canvas.redbox. --&gt;
  &lt;button x="110" text="add cyan"
            onclick="if (canvas.redbox['cyan'] == null) 
                       new mybox(canvas.redbox, { name: 'cyan', bgcolor: 0x00ffff })"/&gt;

  &lt;!-- Remove cyan view from redbox. --&gt;
  &lt;button x="110" y="30" text="remove cyan"
            onclick="if (canvas.redbox['cyan'] != null) canvas.redbox.cyan.destroy()"/&gt;

&lt;/canvas&gt;
</example>

<p>全てのクラスはグローバルネームスペース内で定義されています。もし、クラスを動的にインスタンス化したいならば、<code>new
global[classString](...)</code>のように記述することができます。先に挙げた例を使うと、myboxは<code>new global['mybox'](canvas.redbox, { bgcolor: 0x00ffff
})</code>のようにインスタンス化することができます。
</p>

<p>
タグクラスの名前は、JavaScriptの片割れのようにいつも同じというわけではないことに気を付けてください。例えば、<code>&lt;view&gt;</code> は、スクリプト上では実際は<code>LzView</code>であり、<code>&lt;node&gt;</code> は<code>LzNode</code>です。従って、スクリプトによってviewをインスタンス化するには、<code>new view(...)</code><b>ではなく</b>、<code>new LzView(...)</code>と記述します。LZXタグをJavaScriptにマップする方法についての詳細は、<b>LZXリファレンス</b>を参照のこと。
</p>


<!--======= --> 
<!-- Using  -->
<!--======= --> 
<h2>LZXクラスの使用</h2>

<!--========================================-->
<!-- Basic approach to implementing classes -->
<!--========================================-->
<h3>実行クラスへの基本的なアプローチ</h3>

<p>クラスを記述するためのやり方は、クラスタグを宣言してcanvas上にそのオブジェクトのインスタンスを持つだけです。これにより、クラスを設計している間に、その外観がどのように見えるかをつかむためのフレームワークを得ることができるでしょう。例：</p>

<example extract="false">
&lt;canvas&gt;
  &lt;class name="myclass"&gt;
    ...
  &lt;/class&gt;
  
  &lt;myclass/&gt;
&lt;/canvas&gt;
</example>

<p>任意で、まず最初にviewを記述しそれをクラスに翻訳することによって、クラスの概略を述べることもできます。この方法の欠点は、<code>classroot</code>キーワードが使用できないことと、属性が宣言されないことです。
</p>

<!--================== --> 
<!-- Inheriting views  -->
<!--================== --> 
<h3>継承されたview</h3>
<p>上位クラスから継承されているトップレベルviewは、サブクラスのトップレベルに配置されます。上位クラスから継承されているviewが、最初に順番に配置されるでしょう。このことは、サブビューの配列を調べることによって確認できます。</p>

<example title="Inheriting views">
&lt;canvas debug="true"&gt;
  &lt;debug y="215" width="435"/&gt;
  
  &lt;class name="one"&gt;
    &lt;view name="r" bgcolor="red" width="200" height="200"/&gt;
  &lt;/class&gt;
  
  &lt;class name="two" extends="one"&gt;
    &lt;view name="g" bgcolor="green" width="100" height="100"/&gt;
  &lt;/class&gt;
  
  &lt;class name="three" extends="two"&gt;
    &lt;view name="t" bgcolor="teal" width="50" height="50"/&gt;
    &lt;view name="y" bgcolor="yellow" width="25" height="25"/&gt;
  &lt;/class&gt;
  
  &lt;three id="mysubclass" oninit="Debug.write('subviews: ' + this.subviews)"/&gt;
&lt;/canvas&gt;
</example>

<p>
クラスのインスタンス内で宣言されているビューは、<attribute>defaultplacement</attribute>属性によって宣言されていないかぎり、クラスのトップレベルに配置されます。これらのビューはサブビュー配列内では後ろのほうに配置されるでしょう。<attribute>defaultplacement</attribute>属性は、宣言されたビューが、クラスの階層のどこに位置すべきであるかをクラスに伝えます。これに関しては、次のセクションでより詳しく説明します。
</p>

<example title="Inherited view order">
&lt;canvas debug="true" height="250"&gt;
  &lt;debug y="115" width="330"/&gt;
  &lt;class name="foo"&gt;
    &lt;view name="r" bgcolor="red" width="100" height="100"/&gt;
  &lt;/class&gt;
  
  &lt;foo name="myfoo" oninit="Debug.write('subviews: ' + this.subviews)"&gt;
    &lt;view name="y" bgcolor="yellow" width="50" height="50"/&gt;
  &lt;/foo&gt;
&lt;/canvas&gt;
</example>

<p>
サブビュー配列内で、ビュー<varname>y</varname>がどのようにビュー<varname>r</varname>の後に従っているかに注意してください。もし、<tagname>simplelayout</tagname>がビュー<varname>myfoo</varname>内に配置されていれば、それらは<varname>r</varname>の後に<varname>y</varname>が続くという順序で表示されるでしょう。
</p>

<example title="Inherited view order with simplelayout">
&lt;canvas debug="true" height="250"&gt;
  &lt;debug x="75" y="115" width="330"/&gt;
  
  &lt;class name="foo"&gt;
    &lt;view name="r" bgcolor="red" width="100" height="100"/&gt;
  &lt;/class&gt;
  
  &lt;foo name="myfoo" oninit="Debug.write('subviews: ' + this.subviews)"&gt;
    &lt;simplelayout/&gt;
    &lt;view name="y" bgcolor="yellow" width="50" height="50"/&gt;
  &lt;/foo&gt;
&lt;/canvas&gt;
</example>

<!--===========-->
<!-- Placement -->
<!--===========-->
<h3>配置</h3>

<p>Tクラスの内部構造は、一般的にその階層上の子には見えないものである。デフォルトでは、クラスの内部に現れるインスタンスは、クラスのトップレベルインスタンスの子になります。これは一般的に、コンテナクラスにとって望ましいものではありません。例えば、</p>

<example title="Undesired placement">
&lt;canvas height="50"&gt;
  &lt;class name="myframe" extends="view"&gt;
    &lt;attribute name="bgcolor" value="red"/&gt;
    &lt;view x="5" y="5" width="${parent.width-10}"
               height="${parent.height-10}"
               bgcolor="#FFFFCC"/&gt;
  &lt;/class&gt;
  
  &lt;!-- make an instance of myframe with text inside it--&gt;
  &lt;myframe width="220" height="20"&gt;
    &lt;text&gt;This is some text&lt;/text&gt;
  &lt;/myframe&gt;
&lt;/canvas&gt;
</example>

<p>
この行動は、<attribute>defaultplacement</attribute>属性か、あるいは<method>determinePlacement</method>メソッドを使って帰ることができます。<attribute>defaultplacement</attribute>を使うのは簡潔です−これは、名前から子が帰する（所属する）べきサブビューを特定するクラス属性です。子は、名前が適合する最初のサブビューに帰します（所属します）。もし、適合するものがない場合には、その子はクラスのトップレベル節にサブビューとして配置されます。もし、<attribute>defaultplacement</attribute>が特定されない場合にも、このようになります。
</p>

<p>
<attribute>defaultplacement</attribute> 属性は、常に属性中で<code>type=&quot;string&quot;</code>によって宣言されるべきであることに注意してください。
</p>

<example title="Placing a child in desired subview">
&lt;canvas height="50"&gt;
  &lt;class name="myframe" extends="view"&gt;
    &lt;attribute name="bgcolor" value="red"/&gt;
    
    &lt;!-- child views of class instances will be placed in the first view
            called insideview --&gt;
    &lt;attribute name="defaultplacement" value="insideview" type="string"/&gt;
    
    &lt;view x="5" y="5" width="${parent.width-10}" name="insideview"
                height="${parent.height-10}" 
                bgcolor="#FFFFCC"/&gt;
  &lt;/class&gt;
  &lt;!-- make an instance of myframe with text inside it--&gt;
  &lt;myframe width="220" height="50"&gt;
    &lt;text&gt;This is some text&lt;/text&gt;
  &lt;/myframe&gt;
&lt;/canvas&gt;
</example>

<p>クラス内で宣言された要素は、配置について考慮されていませんが、サブクラスやクラスインスタンス内の子では、考慮されています。</p>

<example title="Defaultplacement">
&lt;canvas height="150"&gt;
  &lt;class name="myframe" extends="view"&gt;
      &lt;attribute name="bgcolor" value="red"/&gt;

      &lt;attribute name="defaultplacement" value="'insideview'"/&gt;

      &lt;view x="5" y="5" width="${parent.width-10}" name="insideview"
              height="${parent.height-10}" 
              bgcolor="#FFFFCC"/&gt;

      &lt;!-- this view is not affected by defaultplacement --&gt;
      &lt;!-- because it's declared in the class.           --&gt; 
      &lt;view x="5" y="${parent.height}" name="anotherview" 
            width="${parent.width-10}" height="10"
            bgcolor="blue"/&gt;
  &lt;/class&gt;

  &lt;class name="subframe" extends="myframe"&gt;
    &lt;!-- the layout and text will be placed in insideview of myframe --&gt;
    &lt;simplelayout axis="y"/&gt;
    &lt;text bgcolor="teal"&gt;subframe text&lt;/text&gt;
  &lt;/class&gt;


  &lt;myframe width="220" height="50"&gt;
    &lt;!-- this will be placed in insideview --&gt;
    &lt;text&gt;This is some text&lt;/text&gt;
  &lt;/myframe&gt;

  &lt;subframe width="220" height="50" y="70"&gt;
    &lt;text bgcolor="green"&gt;More subframe text&lt;/text&gt;
  &lt;/subframe&gt;
&lt;/canvas&gt;
</example>

<h4>レイアウト配置</h4>

<p>
属性として宣言されているレイアウトは配置を考慮されています。これはしばしば望まれる行動です、というのも、これによってサブクラスやクラスインスタンスが、デフォルトの配置にあるビュー用にレイアウトを修正することが容易になるからです。この行動を無効にするために、<attribute>layout</attribute>属性に存在しない<code>placement</code>（例：<code>placement: null</code>）をセットすることができます。<attribute>placement</attribute>属性は、要素のコンテナ（内容）に、コンテナの内部階層内で、どこに行くべきかを伝えます。もし、コンテナが<attribute>defaultplacement</attribute>を持っていれば、<code>placement</code>値は優先権を持ちます。その代わりとして、defaultplacementをクラス内でタグ要素として宣言することにより、defaultplacementでレイアウトを操作することはできない、ということをはっきりさせることができます。
</p>

<example title="Layout placement">
&lt;canvas&gt;
  &lt;!-- the layout attribute will be placed in the red view --&gt;
  &lt;class name="myplacement" defaultplacement="'red'" layout="axis: x; spacing: 5"&gt;
    &lt;!-- this layout element applies to views inside of class --&gt;
    &lt;simplelayout spacing="10"/&gt;
    &lt;view name="red" bgcolor="red" width="150" height="150"/&gt;
    &lt;view name="yellow" bgcolor="yellow" width="150" height="150"/&gt;
  &lt;/class&gt;

  &lt;myplacement&gt;
    &lt;!-- placement overrides defaultplacement --&gt;
    &lt;view name="blue" bgcolor="blue" width="50" height="50" placement="yellow"/&gt;

    &lt;!-- green and teal will be placed in red --&gt;
    &lt;view name="green" width="50" height="50" bgcolor="green"/&gt;
    &lt;view name="teal" width="50" height="50" bgcolor="teal"/&gt;
  &lt;/myplacement&gt;

&lt;/canvas&gt;
</example>

<!-- ================ -->
<!-- Immediate parent -->
<!-- ================ -->
<h4>直接のParent</h4>

<p>
<attribute>defaultplacement</attribute>や<attribute>placement</attribute> を使って配置されている子はしばしば2つのparent型を持ちます。<field>parent</field>とは、コンストラクタ内で子の先祖として渡された節への参照です（例：<code>new
childClass(parent, args)</code>）。もし、子がタグ内で宣言されることによって生成された場合には、親はその語彙の親と なります。その語彙の親はそれを内包するタグです。
</p>

<p>
<field>immediateParent</field>とは子が配置されていた節のことを言います。もし、どのような配置も指定されていなければ、その値は<field>parent</field>と同じになるでしょう。
</p>

<example title="Parent vs. immediateParent">
&lt;canvas debug="true" height="200"&gt;    
  &lt;debug x="155"/&gt;

  &lt;class name="container" defaultplacement="'red'"&gt;
    &lt;view name="red" bgcolor="red" width="150" height="150"/&gt;
  &lt;/class&gt;

  &lt;!-- yellow's parent is top and its immediateParent   --&gt;
  &lt;!-- is red, since that's where it's actually placed. --&gt;
  &lt;container name="top"&gt;
    &lt;view name="yellow" bgcolor="yellow" width="50" height="50"&gt;
      &lt;method event="oninit"&gt;
        Debug.write('parent: ', this.parent);
        Debug.write('immediateParent: ', this.immediateParent);
      &lt;/method&gt;
    &lt;/view&gt;
  &lt;/container&gt;
&lt;/canvas&gt;
</example>

<h4>defaultPlacementノードのリファレンスを入手する</h4>

<p>デフォルトの配置への参照を必要とするクラスのインスタンスがあるかもしれません。よい方法としては、見つかるまで暮らすのサブノードを検索するやり方があります。</p>

<example title="Obtaining a reference to the defaultPlacement node">
&lt;canvas debug="true" height="200"&gt;
  &lt;debug x="155"/&gt;

  &lt;class name="container" defaultplacement="'red'"&gt;
    &lt;attribute name="contentview" value="null" type="expression"/&gt;

    &lt;method name="init"&gt;
      super.init();

      // get a reference to the content node
      if ( this.contentview == null ) {
        if ( this.defaultplacement != null ){
          this.contentview = this.searchSubnodes( "name" , this.defaultplacement );
        } else {
          this.contentview = this;
        }
      }
      
      Debug.write("content view", this.contentview);
    &lt;/method&gt;

    &lt;view name="green" bgcolor="green" width="100" height="100"&gt;
      &lt;view name="yellow" bgcolor="yellow" width="50%" height="50%"&gt;
        &lt;view name="red" bgcolor="red" width="50%" height="50%"/&gt;
      &lt;/view&gt;
    &lt;/view&gt;
  &lt;/class&gt;

  &lt;container name="top"/&gt;
&lt;/canvas&gt;
</example>

<!-- ================== -->
<!-- determinePlacement -->
<!-- ================== -->
<h4><method>determinePlacement</method>を使って、配置の動作を無効化する</h4>

<p>
節は、子の<field>immediateParent</field>を決定するために<method>determinePlacement</method>メソッドを呼び出します。このメソッドは、配置属性を持つサブノードか、あるいは、もしこの節がnullでない<attribute>defaultplacement</attribute>を持ってる場合には全てのサブノードのためにのみ呼び出されます。サブノードの<attribute>placement</attribute>属性は、親の<attribute>defaultplacement</attribute>を無効にします。子のメソッドは、<varname>placement</varname>パラメータ内で与えられた名前のサブノードを探し、その節を返します。もし、該当する節が存在しなければ、<varname>this</varname>を返します。コードは基本的にこのようになります：
</p>

<example extract="false">
&lt;!-- subnode: the child node to place         --&gt;
&lt;!-- placement: the node to place the subnode --&gt;
&lt;!-- args: init args of the child subnode     --&gt;
&lt;method name="determinePlacement" args="subnode, placement, args"&gt;
  // ignore placement if set
  if ( args.ignoreplacement ){
      return this;
  }

  if ( placement == null ){
    var p = null;
  } else {
    var p = this.searchSubnodes( "name" , placement );
  }

  return p == null ? this : p;
&lt;/method&gt;
</example>

<p>
サブクラスは、<varname>placement</varname>パラメータに異なる動作、または追加の効果を持たせるようにこのメソッドを実行します。例えば、サブノードは<field>parent</field>と<field>immediateParent</field>を同じものととらえることもできます。
</p>

<example title="Overriding determinePlacement">
&lt;canvas debug="true" height="200"&gt;
  &lt;debug x="155"/&gt;

  &lt;class name="container" defaultplacement="'red'"&gt;
    &lt;!-- setting subnode's parent to be the same as immediateParent --&gt;
    &lt;method name="determinePlacement" args="subnode, place, args"&gt;
      var p = super.determinePlacement(subnode, place, args);
      subnode.parent = p;
      return p;
    &lt;/method&gt;

    &lt;view name="blue" bgcolor="blue" width="100" height="100"&gt;
      &lt;view name="red" bgcolor="red" width="150" height="150"/&gt;
    &lt;/view&gt;
  &lt;/class&gt;

  &lt;container name="top"&gt;
    &lt;view name="yellow" bgcolor="yellow" width="50" height="50"&gt;
      &lt;method event="oninit"&gt;
        Debug.write('parent: ', this.parent);
        Debug.write('immediateParent: ', this.immediateParent);
      &lt;/method&gt;
    &lt;/view&gt;
  &lt;/container&gt;
&lt;/canvas&gt;
</example>


<!--=======-->
<!-- Steps -->
<!--=======-->
<h3>構文と初期化</h3>

<p>
複雑なクラスを記述する時には、クラスがどのように組み立てられ、初期化されているのかを深く理解することが必要不可欠です。クラスインスタンスが完全に初期化される前に、いくつかの段階があります。この過程を説明することはこの章の目的とは外れてしまいますが、重要なメソッドとイベント、そしてそれらが呼び出される一連の流れについては紹介します。インスタンス化については、<xref
linkend="initialization-and-instantiation"/>を参照のこと。
</p>

<p>
<method>construct</method>メソッド節は、ビューシステム内で可能な限り早く呼ばれます。それは、どのような引数が適用されるよりも前に呼び出されるのです。これは、LZXクラスのクラスコンストラクタを記述する代わりに無効にするためのメソッドです。もし、子のメソッドが無効化されたら、上位クラスのメソッドが呼ばれるべきであるか、あるいは結果が相当に予測不可能であるかになるでしょう。例えば、これは、組み立てられたクラスが、その親の<method>determinePlacement</method>メソッドを呼び出して自分自身をそのコンテナ内に配置するというメソッドです。もし、上位クラスの組み立てメソッドが呼ばれなければ、クラスのインスタンスは正しく配置されないかもしれません。
</p>

<p>
他の手段として、<event>onconstruct</event>イベントを使うこともできます。これは、<method>construct</method>が呼ばれた後に、instantiatorによって送られるものです。<event>onconstruct</event>はインスタンス化プロセスのちょうど最後に起こりますが、それはどんなサブノードが生成されるよりも、あるいは参照がなされるよりも前になります。
</p>

<p>コンストラクションはトップダウン（親からサブビューへ）で起り、その一方で初期化はボトムアップ（サブビューから先祖へ）で起こることを心に留めておいてください。</p>

<example title="Construction and initialization">
&lt;canvas debug="true" height="180"&gt;
  &lt;debug height="160"/&gt;

  &lt;class name="container"&gt;
    &lt;!-- Don't forget to call super.construct(parent,args)!! --&gt;
    &lt;method name="construct" args="parent,args"&gt;
      Debug.write("container construct", parent, args);
      super.construct(parent, args);
    &lt;/method&gt;

    &lt;!-- The onconstruct event --&gt;
    &lt;method event="onconstruct" args="v"&gt;
      Debug.write("container onconstruct", v);
    &lt;/method&gt;

    &lt;method name="init"&gt;
      Debug.write("container init");
    &lt;/method&gt;

    &lt;method event="oninit"&gt;
      Debug.write("container oninit");
    &lt;/method&gt;
  &lt;/class&gt;

  &lt;container&gt;
    &lt;view name="outside" oninit="Debug.write('outside oninit')"&gt;
      &lt;view name="inside" oninit="Debug.write('inside oninit')"/&gt;
    &lt;/view&gt;        
  &lt;/container&gt;
&lt;/canvas&gt;
</example>

<p>
続くインスタンス化（例：<event>onconstruct</event>が送られた後）と、もし子説（ノード）がある場合、
<method>createChildren</method>メソッドが呼ばれます。子のメソッドは子オブジェクトの配列をパラメータとして使います。
</p>

<dl>
  <dt><field>name</field></dt>
  <dd>インスタンス化するための子のクラス名</dd>
  <dt><field>attrs</field></dt>
  <dd>例えば、<attribute>name</attribute>、<attribute>height</attribute>などで子を初期化するための属性
  </dd>
  <dt><field>children</field></dt>
  <dd>子オブジェクトの配列。存在しない場合には未定義でも可。</dd>
</dl>

<example title="createChildren()">
&lt;canvas debug="true" height="180"&gt;
  &lt;debug height="160"/&gt;

  &lt;class name="container"&gt;
    &lt;method event="onconstruct" args="v"&gt;
      Debug.write("container onconstruct", v);
    &lt;/method&gt;

    &lt;method name="createChildren" args="c"&gt;
      Debug.write("container createChildren", c);
      Debug.write("    c[0].name:", c[0].name);
      Debug.write("    c[0].attrs:", c[0].attrs);
      Debug.write("    c[0].children:", c[0].children);
      super.createChildren(c);
    &lt;/method&gt;
  &lt;/class&gt;

  &lt;container&gt;
   &lt;view name="outside"&gt;
     &lt;view name="inside"/&gt;
   &lt;/view&gt;
  &lt;/container&gt;
&lt;/canvas&gt;
</example>

<p>要約すると、メソッドの基本的なタイミング順序とイベント呼出はこのようになると予測することができます。</p>

<ol>
  <li><method>construct</method>メソッドが呼ばれる。</li>
  <li><method>determinePlacement</method>メソッドが呼ばれる。（親メソッドが呼ばれるので、親はこのオブジェクトをどこに配置すべきか分かる）</li>
  <li><event>onconstruct</event>イベントが送られる。</li>
  <li><method>createChildren</method>が呼ばれる。（各子がインスタンス化され初期化される）</li>
  <li><method>init</method>が呼ばれる。</li>
  <li><event>oninit</event>が呼ばれる。</li>
</ol>

<fixme>Is this the same information as in <xref linkend="initialization-and-instantiation"/>?  Should it be consolidated?</fixme>

<h2>用語集</h2>

<dl>
  <dt><code>classroot</code></dt>
  <dd>クラスのインスタンスのルート節を表す速記</dd>
  
  <dt><attribute>extends</attribute></dt>
  <dd>クラス定義でサブクラスを生成するのに使われるキーワード</dd>
  
  <dt>inheritance</dt>
  <dd>上位クラスで定義された変数とメソッドを自動的に含むクラスの概念</dd>
  
  <dt>instantiation</dt>
  <dd>クラスやオブジェクトのインスタンスを生成するアクション</dd>
  
  <dt>overloading</dt>
  <dd>多様な関数を示すのに一つのアイデンティファイアを使うこと</dd>
  
  <dt>overriding</dt>
  <dd>サブクラス内で、その上位クラスから異なるメソッドの実行を行うこと</dd>
  
  <dt>subclass</dt>
  <dd>別のクラスから派生するクラス</dd>
  
  <dt><code>super</code></dt>
  <dd>サブクラスがその上位クラスのメソッドを呼び出すのを許可するキーワード操作</dd>
  
  <dt>superclass</dt>
  <dd>サブクラスの属性やメソッドが派生する大元のクラス</dd>
</dl>
</body>
</html>
<!-- * X_LZ_COPYRIGHT_BEGIN ***************************************************
* Copyright 2001-2004 Laszlo Systems, Inc.  All Rights Reserved.              *
* Use is subject to license terms.                                            *
* X_LZ_COPYRIGHT_END ****************************************************** -->
